package com.bsoft.gol.hcb.service.templateSheet.utils;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtils {

    public static String mapToXml(Map<String, Object> paramsMap, String root, StringBuilder sb) {
        sb.append("<" + root + ">");
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            String xmlKey = firstLetterCapitalize(entry.getKey());
            if (entry.getValue() instanceof List){
                List value = (List) entry.getValue();
                for (Object o : value) {
                    if (o instanceof Map){
                        Map<String,Object> map = (Map<String, Object>) o;
                        mapToXml(map,xmlKey,sb);
                    }
                }
            }else if (entry.getValue() instanceof Map){
                Map<String,Object> map = (Map<String, Object>) entry.getValue();
                mapToXml(map,xmlKey,sb);
            }else {
                if (entry.getValue()!=null){
                    sb.append("<").append(xmlKey).append(">")
                            .append(entry.getValue())
                            .append("</").append(xmlKey).append(">");
                }
            }
        }
        sb.append("</" + root + ">");
        return sb.toString();
    }

    public static Map<String, Object> xmlToMap(String xml) throws DocumentException {
        Map map = new HashMap();
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
        Element root = document.getRootElement();
        elementTomap(root, map);
        return map;
    }

    private static Map<String, Object> elementTomap(Element outele, Map<String, Object> outmap) {
        List<Element> list = outele.elements();
        int size = list.size();
        if (size == 0) {
            outmap.put(firstLetterLowercase(outele.getName()), outele.getTextTrim());
        } else {
            Map<String, Object> innermap = new HashMap<String, Object>();
            int i = 1;

            for (Element ele1 : list) {
                String eleName = firstLetterLowercase(ele1.getName());

                String value = ele1.getText();
                Object obj = innermap.get(eleName);
                if (obj == null) {
                    elementTomap(ele1, innermap);
                } else {
                    if (obj instanceof java.util.Map) {
                        List<Map<String, Object>> list1 = new ArrayList<Map<String, Object>>();
                        list1.add((Map<String, Object>) innermap.remove(eleName));
                        elementTomap(ele1, innermap);
                        list1.add((Map<String, Object>) innermap.remove(eleName));
                        innermap.put(eleName, list1);
                    } else if (obj instanceof String) {

                        innermap.put(eleName + i, value);
                        i++;
                    } else {
                        elementTomap(ele1, innermap);
                        Map<String, Object> listValue = (Map<String, Object>) innermap.get(eleName);
                        ((List<Map<String, Object>>) obj).add(listValue);
                        innermap.put(eleName, obj);
                    }

                }
            }
            outmap.put(firstLetterLowercase(outele.getName()), innermap);
        }
        return outmap;
    }

    public static String firstLetterCapitalize(String str) {
        byte[] items = str.getBytes();
        if (items[0]>='a' && items[0]<='z'){
            items[0] = (byte) ((char) items[0] - 'a' + 'A');
        }
        return new String(items);
    }

    public static String firstLetterLowercase(String str) {
        byte[] items = str.getBytes();
        if (items[0]>='A' && items[0]<='Z'){
            items[0] = (byte) ((char) items[0] - 'A' + 'a');
        }
        return new String(items);
    }
}
